package com.easyjob.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.easyjob.entity.enums.CategoryTypeEnum;
import com.easyjob.entity.enums.PageSize;
import com.easyjob.entity.enums.ResponseCodeEnum;
import com.easyjob.entity.po.*;
import com.easyjob.entity.query.CategoryQuery;
import com.easyjob.entity.query.ExamQuestionQuery;
import com.easyjob.entity.query.QuestionInfoQuery;
import com.easyjob.entity.query.SimplePage;
import com.easyjob.entity.vo.*;
import com.easyjob.exception.BusinessException;
import com.easyjob.mappers.CategoryMapper;
import com.easyjob.mappers.ExamQuestionMapper;
import com.easyjob.mappers.QuestionInfoMapper;
import com.easyjob.mappers.plus.*;
import com.easyjob.service.CategoryService;
import com.easyjob.utils.BeanCopyUtils;
import com.easyjob.utils.StringTools;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;


/**
 * 分类 业务接口实现
 */
@Service("categoryService")
public class CategoryServiceImpl implements CategoryService {

    @Resource
    private CategoryMapper<Category, CategoryQuery> categoryMapper;

    @Resource
    private QuestionInfoMapper<QuestionInfo, QuestionInfoQuery> questionInfoMapper;

    @Resource
    private ExamQuestionMapper<ExamQuestion, ExamQuestionQuery> examQuestionMapper;

    @Resource
    private BankMapper bankMapper;

    @Resource
    private CategoryPlusMapper categoryPlusMapper;

    @Resource
    private ChapterPlusMapper chapterPlusMapper;

    @Resource
    private QuestionPlusMapper questionPlusMapper;

    @Resource
    private ExamModelMapper examModelMapper;


    /**
     * 根据条件查询列表
     */
    @Override
    public List<Category> findListByParam(CategoryQuery param) {
        return this.categoryMapper.selectList(param);
    }

    /**
     * 根据条件查询列表
     */
    @Override
    public Integer findCountByParam(CategoryQuery param) {
        return categoryMapper.selectCount(param);
    }

    /**
     * 分页查询方法
     */
    @Override
    public PaginationResultVO<Category> findListByPage(CategoryQuery param) {
        int count = this.findCountByParam(param);
        int pageSize = param.getPageSize() == null ? PageSize.SIZE15.getSize() : param.getPageSize();
        SimplePage page = new SimplePage(param.getPageNo(), count, pageSize);
        param.setSimplePage(page);
        List<Category> list = this.findListByParam(param);
        list = list.stream().peek(item -> {
            Integer bankId = item.getBankId();
            String bankName = bankMapper.selectOne(new QueryWrapper<QuestionBank>().eq("bank_id", bankId)).getBankName();
            item.setBankName(bankName);
        }).collect(Collectors.toList());
        PaginationResultVO<Category> result = new PaginationResultVO(count, page.getPageSize(), page.getPageNo(), page.getPageTotal(), list);
        return result;
    }

    /**
     * 新增
     */
    @Override
    public Integer add(Category bean) {
        return this.categoryMapper.insert(bean);
    }

    /**
     * 批量新增
     */
    @Override
    public Integer addBatch(List<Category> listBean) {
        if (listBean == null || listBean.isEmpty()) {
            return 0;
        }
        return this.categoryMapper.insertBatch(listBean);
    }

    /**
     * 批量新增或者修改
     */
    @Override
    public Integer addOrUpdateBatch(List<Category> listBean) {
        if (listBean == null || listBean.isEmpty()) {
            return 0;
        }
        return this.categoryMapper.insertOrUpdateBatch(listBean);
    }

    /**
     * 多条件更新
     */
    @Override
    public Integer updateByParam(Category bean, CategoryQuery param) {
        StringTools.checkParam(param);
        return this.categoryMapper.updateByParam(bean, param);
    }

    /**
     * 多条件删除
     */
    @Override
    public Integer deleteByParam(CategoryQuery param) {
        StringTools.checkParam(param);
        return this.categoryMapper.deleteByParam(param);
    }

    /**
     * 根据CategoryId获取对象
     */
    @Override
    public Category getCategoryByCategoryId(Integer categoryId) {
        return this.categoryMapper.selectByCategoryId(categoryId);
    }

    /**
     * 根据CategoryId修改
     */
    @Override
    public Integer updateCategoryByCategoryId(Category bean, Integer categoryId) {
        return this.categoryMapper.updateByCategoryId(bean, categoryId);
    }

    /**
     * 根据CategoryId删除
     */
    @Override
    public Integer deleteCategoryByCategoryId(Integer categoryId) {
        QuestionInfoQuery questionInfoQuery = new QuestionInfoQuery();
        questionInfoQuery.setCategoryId(categoryId);
        Integer count = questionInfoMapper.selectCount(questionInfoQuery);
        if (count > 0) {
            throw new BusinessException("问题库正在使用该分类无法删除");
        }
        ExamQuestionQuery examQuestionQuery = new ExamQuestionQuery();
        examQuestionQuery.setCategoryId(categoryId);
        count = Math.toIntExact(chapterPlusMapper.selectCount(new QueryWrapper<Chapter>().eq("category_id", categoryId)));
        if (count > 0) {
            throw new BusinessException("章节库正在使用该分类无法删除");
        }
        return this.categoryMapper.deleteByCategoryId(categoryId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveCategory(Category category) {
        if (null == category.getCategoryId()) {
            CategoryQuery categoryQuery = new CategoryQuery();
            Integer count = this.categoryMapper.selectCount(categoryQuery);
            category.setSort(count + 1);
            this.categoryMapper.insert(category);
        } else {
            categoryPlusMapper.update(category, new UpdateWrapper<Category>().eq("category_id", category.getCategoryId()));
//            this.categoryMapper.updateByCategoryId(category, category.getCategoryId());
        }
    }

    @Override
    public List<Category> loadAllCategoryByQuery(Integer bankId) {
        if (bankId == null) return categoryPlusMapper.selectList(null);
        return categoryPlusMapper.selectList(new QueryWrapper<Category>().eq("bank_id", bankId));
    }

    @Override
    public List<Category> loadAllCategory() {
        CategoryQuery categoryQuery = new CategoryQuery();
        categoryQuery.setOrderBy("sort asc");
        return this.categoryMapper.selectList(categoryQuery);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void changeSort(String categoryIds) {
        String[] categoryIdArray = categoryIds.split(",");
        Integer index = 1;
        for (String categoryIdStr : categoryIdArray) {
            Integer categoryId = Integer.parseInt(categoryIdStr);
            Category category = new Category();
            category.setSort(index);
            categoryMapper.updateByCategoryId(category, categoryId);
            index++;
        }
    }

    @Override
    public List<CategoryInfoVo> loadAllCategoryInfo(Integer bankId) {
        List<Category> categoryList = categoryPlusMapper.selectList(new QueryWrapper<Category>().eq("bank_id", bankId).orderByAsc("sort"));
        List<CategoryInfoVo> categoryInfoVoList = categoryList.parallelStream().map(item -> {
            CategoryInfoVo infoQuery = BeanCopyUtils.copyBean(item, CategoryInfoVo.class);
            List<Chapter> chapterList = chapterPlusMapper.selectList(new QueryWrapper<Chapter>().eq("category_id", item.getCategoryId()).orderByAsc("sort"));
            List<ChapterInfoVo> chapterInfoVoList = chapterList.parallelStream().map(subItem -> {
                ChapterInfoVo chapterInfoVo = BeanCopyUtils.copyBean(subItem, ChapterInfoVo.class);
                Integer chapterId = subItem.getChapterId();
                int count = questionPlusMapper.selectCount(new QueryWrapper<ExamQuestion>().eq("chapter_id", chapterId)).intValue();
                chapterInfoVo.setQuestionCount(count);
                return chapterInfoVo;
            }).collect(Collectors.toList());
            infoQuery.setChapterList(chapterInfoVoList);
            return infoQuery;
        }).collect(Collectors.toList());
        return categoryInfoVoList;
    }

    @Override
    public List<CategoryVo> loadCategory(Integer bankId) {
        List<Category> categoryList = categoryPlusMapper.selectList(new QueryWrapper<Category>().eq("bank_id", bankId).orderByAsc("sort"));
        List<CategoryVo> categoryVoList = categoryList.parallelStream().map(item -> {
            CategoryVo categoryVo = BeanCopyUtils.copyBean(item, CategoryVo.class);
            List<Chapter> chapterList = chapterPlusMapper.selectList(new QueryWrapper<Chapter>().eq("category_id", item.getCategoryId()).orderByAsc("sort"));
            chapterList.forEach(subItem -> {
                Integer chapterId = subItem.getChapterId();
                int count = questionPlusMapper.selectCount(new QueryWrapper<ExamQuestion>().eq("chapter_id", chapterId)).intValue();
                categoryVo.setQuestionCount(categoryVo.getQuestionCount() + count);
            });
            return categoryVo;
        }).collect(Collectors.toList());
        return categoryVoList;
    }

    @Override
    public List<ChapterVo> loadChapter(Integer categoryId) {
        List<Chapter> chapterList = chapterPlusMapper.selectList(new LambdaQueryWrapper<Chapter>().eq(Chapter::getCategoryId, categoryId).orderByAsc(Chapter::getSort));
        List<ChapterVo> chapterVoList = BeanCopyUtils.copyBeanList(chapterList, ChapterVo.class);
        return chapterVoList;
    }

    @Override
    public List<ModelVo> loadModels() {
        List<ExamModel> examModels = examModelMapper.selectList(null);
        List<ModelVo> modelVoList = BeanCopyUtils.copyBeanList(examModels, ModelVo.class);
        modelVoList = convert(modelVoList, "-1");
        return modelVoList;
    }

    private List<ModelVo> convert(List<ModelVo> examModels, String pId) {
        List<ModelVo> children = new ArrayList<>();
        for (ModelVo p : examModels) {
            if (p.getPId().equals(pId)) {
                p.setChildren(convert(examModels, p.getValue()));
                children.add(p);
            }
        }
        return children;
    }
}